// 导出方法


// 导入方法
export {
  // 方法声明
  printLog,
  crc16,
  bufferToHexString,
  butterToUint8Array,
  combineProtocolData,
  arrayToUInt16,
  arrayToInt16,
  arrayToInt32,
  arrayToUInt32,
  dec2hex,
  bytesToIntLittleEndian,
  intToBytesLittleEndian,
  intToBytesMinEndian,
  wxLogin,
  getDialList,
}

/**
 * 统一打印日志方法
 * @param {*} msg 打印说明
 * @param {*} obj 打印内容如：一个对象会自动转成JSON 字符串
 */
function printLog(msg, obj) {

  let pre = "[YCSDK]: "

  if (obj == null || obj == undefined) {
    console.log(pre + msg)
    return
  }

  // obj是一对象
  if (Object.prototype.toString.call(obj) === '[object Object]') {
    var description = "";
    for (var i in obj) {
      description += i + " = " + obj[i] + "\n";
    }

    console.log(pre + msg + '\n' + description)

    return
  }

  // console.log(JSON.stringify(obj))
  console.log(pre + msg, obj)
}


// ArrayBuffer转16进度字符串示例
function bufferToHexString(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}

/**
 * 二进制数转换整数数组
 * @param {二进制数据} buffer 
 */
function butterToUint8Array(buffer) {
  return Array.prototype.slice.call(new Uint8Array(buffer));
}

/**
 * 计算这串数据的CRC16
 * @param {单字节数组} arr 
 */
function crc16(arr) {

  let crcData = 0xFFFF;

  if (arr === null ||
    arr === undefined ||
    arr === "") {

    return crcData;
  }

  // 计算
  for (let i = 0; i < arr.length; i++) {
    crcData = ((((crcData >> 8) & 0xFF) | (crcData << 8)) & 0xFFFF)
    crcData ^= (arr[i] & 0xFF)
    crcData ^= ((crcData & 0xFF) >> 4)
    crcData ^= (((crcData << 8 << 4)) & 0xFFFF)
    crcData ^= ((((crcData & 0xFF) << 4) << 1) & 0XFFFF)
  }

  return crcData & 0xFFFF;
}


// MARK: - 构造发送数据的格式内容

/**
 * 生成紧终的数据格式 返回 dataPackage 格式
 * @param {指令的comand} commandID 
 * @param {指令的key} key 
 * @param {指令的其它数据} additionalData 
 * @param {指令的回调} completion
 */
function combineProtocolData(commandID, key, additionalData, completion) {

  // 定义数据类型
  var dataPackage = {
    commandID: commandID,
    key: key,
    additionalData: additionalData,
    buffer: new ArrayBuffer(), // 发送的二进制
    completion: completion // 指令的回调
  }

  // CMD KEY 长度 附加数据
  let array = new Array()
  let index = 0

  // cmd
  array[index++] = dataPackage.commandID

  // key
  array[index++] = dataPackage.key

  // 长度
  let dataLength = 6 +
    (dataPackage.additionalData == null ? 0 : dataPackage.additionalData.length)
  array[index++] = (dataLength & 0xFF)
  array[index++] = ((dataLength >> 8) & 0xFF)

  // 附加数据
  if (dataPackage.additionalData != null) {
    dataPackage.additionalData.forEach((e) => {
      array[index++] = e
    })
  }

  // CRC数据
  let crcData = crc16(array)
  array[index++] = (crcData & 0xFF)
  array[index++] = ((crcData >> 8) & 0xFF)
  // 获得最后的二进制数据
  dataPackage.buffer = new Uint8Array(array).buffer

  return dataPackage
}

// MARK: - 字节合成整数

/**
 * 转换为有符号2字节整数
 * @param {数组} bytes 
 */
function arrayToInt16(bytes) {
  return getView(bytes).getInt16()
}

/**
 * 转换为无符号2字节整数
 * @param {数组} bytes 
 */
function arrayToUInt16(bytes) {
  return getView(bytes).getUint16()
}

/**
 * 转换为有符号4字节整数
 * @param {数组} bytes 
 */
function arrayToInt32(bytes) {
  return getView(bytes).getInt32()
}

/**
 * 转换为无符号4字节整数
 * @param {数组} bytes 
 */
function arrayToUInt32(bytes) {
  return getView(bytes).getUint32()
}

/**
 * 将数字转换为字节数组
 * @param {数字} num 
 */
function getNumberBytes(num) {
  return getUint8Array(1, function (view) {
    view.setUint8(0, num)
  })
}

//将数值写入到视图中，获得其字节数组，大端字节序
function getUint8Array(len, setNum) {
  var buffer = new ArrayBuffer(len); //指定字节长度
  setNum(new DataView(buffer)); //根据不同的类型调用不同的函数来写入数值
  return new Uint8Array(buffer); //创建一个字节数组，从缓存中拿取数据
}

//构建一个视图，把字节数组写到缓存中，索引从0开始，小端字节序
function getView(bytes) {
  let array = bytes.reverse()
  var view = new DataView(new ArrayBuffer(array.length));
  for (var i = 0; i < bytes.length; ++i) {
    view.setUint8(i, array[i]);
  }
  return view;
}

/** 10进制转16进制补0*/
function dec2hex(dec, len) {
  var hex = "";
  while (dec) {
    var last = dec & 15;
    hex = String.fromCharCode(((last > 9) ? 55 : 48) + last) + hex;
    dec >>= 4;
  }
  if (len) {
    while (hex.length < len) hex = '0' + hex;
  }
  return hex;
}



//小端模式 数组转换为整数
function bytesToIntLittleEndian(bytes){
  var val = 0;
  for (var i = bytes.length - 1; i >= 0; i--) {        
      val += bytes[i];    
      if (i != 0) {
          val = val << 8;
      }    
  }
  return val;
}

//小端模式 整数转换为数组
//number 要转换的整型数值
//length 要转成什么byte数组，规定数组的长度
//如uint16，则lenght=2表示两个字节，转成的byte数组长度是length=2
//如uint32，则lenght=2表示两个字节，转成的byte数组长度是length=4
function intToBytesLittleEndian(str, length){
  var ch, st, re = []; 
  for (var i = 0; i < str.length; i++ ) { 
      ch = str.charCodeAt(i);  // get char  
      st = [];                 // set up "stack"  
      console.log(ch+"----123213123"); 
     do {  
          st.push( ch & 0xFF );  // push byte to stack  
          ch = ch >> 8;          // shift value down by 1 byte  
      }    

      while ( ch );  
      // add stack contents to result  
      // done because chars have "wrong" endianness  
      re = re.concat( st.reverse() ); 
  }  
  // return an array of bytes
   
  return re;  

}

//大端模式 字节转换为整数
function bytesToIntBigEndian(bytes){
  var val = 0;
  for (var i = 0; i < bytes.length; ++i) {        
      val += bytes[i];        
      if (i < bytes.length-1) {
          val = val << 8;
      }
  }
  return val;
}

// 大端模式 整数转换字节数组
//number 要转换的整型数值
//length 要转成什么byte数组，规定数组的长度
//如uint16，则lenght=2表示两个字节，转成的byte数组长度是length=2
//如uint32，则lenght=2表示两个字节，转成的byte数组长度是length=4
function intToBytesBigEndian(number, length){
  var bytes = [];
  var i = length;
  do {
  bytes[--i] = number & (255);
  number = number>>8;
  } while (i)
  return bytes;
}
function intToBytesMinEndian(number, length){
  var bytes = [];
  var i = 0;
  do {
  bytes[i++] = number & (255);
  number = number>>8;
  } while (i<length)
  return bytes;
}

// 登录接口
let devUrl = "https://web-api.ycaviation.com/smartam"  // 正式环境
let testUrl = "https://web-api-test-d.ycaviation.com/smartam"  // 测试环境

// 小程序登录
function wxLogin(code, success){
  let param = {
    code
  }
  _request('/oauth/wechat/miniprogram', param, success,'GET')
}

/**
 * 获取表盘
 * @param {表盘} code 
 * @param {宽度} width 
 * @param {高度} height 
 * @param {设备型号} deviceType 
 * @param {缓存} token 
 * @param {回调} success 
 */
function getDialList( deviceType, token, success) {
  let param = {
    code: "cn",
    width: 240,
    height: 240,
    deviceType,
    token
  }
  _request('/app/selectDialplateByCode', param, success, 'GET')
}

function _request(url, param, success, method = 'POST', fail = {}, complete = {}, header = {
  'content-type': 'application/x-www-form-urlencoded',
  'wxMinioProject': 'SmartHealth'
}) {
  console.log("network", devUrl + url, param);
  wx.showLoading({ 
    title: "加载中...",
    // duration: 2000
})
  wx.request({
    url: devUrl + url,
    data: param,
    header: header,
    method: method,
    success: success,
    complete: (res) => {
      if (res.statusCode === 200) {
        // 请求成功的情况
        wx.showToast({
          title: '成功',
          icon: 'success',
          duration: 1500
        });
      } else {
        // 请求失败的情况
        wx.showToast({
          title: res.errMsg || 'fail',
          icon: 'none', // 使用 'none' 可以显示自定义的错误信息而不带图标
          duration: 1500
        });
      }
      // 如果有需要，可以在这里调用 wx.hideLoading()
    },
    fail: fail,
    timeout: 20000
  })
}